﻿using System;
using System.Collections.Generic;

using System.Text;
using Estimate.Common.DBFieldTypes;
using Estimate.Common.Entity;

namespace Estimate.Common.Estimate
{
 

    /// <summary>
    /// 预测数据和实况数据的关系对应类
    /// </summary>
    public class ForeRealLinker
    {
        private static List<RainForeRealCompare> rainRealCompareList;

        private static List<TempForeRealCompare> tempRealCompareList;

        static ForeRealLinker()
        {//初始化对照表
            #region 初始化雨水预测与实况对照条件
            rainRealCompareList = new List<RainForeRealCompare>(42){
                 new RainForeRealCompare(ForeSpanType.FD00_12, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD12_24, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD00_24, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD24_36, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD36_48, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD24_48, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD48_60, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD60_72, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD48_72, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD72_84, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD84_96, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD72_96, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD96_108, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD108_120, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD96_120, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD120_132, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD132_144, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD120_144, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD144_156, ForeClockType.H08, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD156_168, ForeClockType.H08, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD144_168, ForeClockType.H08, RealRainValueType.D88),

                 new RainForeRealCompare(ForeSpanType.FD00_12, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD12_24, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD00_24, ForeClockType.H20, RealRainValueType.D22),

                 new RainForeRealCompare(ForeSpanType.FD24_36, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD36_48, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD24_48, ForeClockType.H20, RealRainValueType.D22),

                 new RainForeRealCompare(ForeSpanType.FD48_60, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD60_72, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD48_72, ForeClockType.H20, RealRainValueType.D22),

                 new RainForeRealCompare(ForeSpanType.FD72_84, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD84_96, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD72_96, ForeClockType.H20, RealRainValueType.D22),

                 new RainForeRealCompare(ForeSpanType.FD96_108, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD108_120, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD96_120, ForeClockType.H20, RealRainValueType.D22),

                 new RainForeRealCompare(ForeSpanType.FD120_132, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD132_144, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD120_144, ForeClockType.H20, RealRainValueType.D22),

                 new RainForeRealCompare(ForeSpanType.FD144_156, ForeClockType.H20, RealRainValueType.D28),
                 new RainForeRealCompare(ForeSpanType.FD156_168, ForeClockType.H20, RealRainValueType.D82),
                 new RainForeRealCompare(ForeSpanType.FD144_168, ForeClockType.H20, RealRainValueType.D22),
            };
#endregion

            #region 初始化气温预测与实况对照条件
            tempRealCompareList = new List<TempForeRealCompare>(28)
            {
                new TempForeRealCompare(ForeSpanType.FD00_24,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD00_24,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD00_24,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD00_24,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),

                new TempForeRealCompare(ForeSpanType.FD24_48,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD24_48,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD24_48,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD24_48,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),

                new TempForeRealCompare(ForeSpanType.FD48_72,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD48_72,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD48_72,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD48_72,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),

                new TempForeRealCompare(ForeSpanType.FD72_96,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD72_96,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD72_96,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD72_96,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),

                new TempForeRealCompare(ForeSpanType.FD96_120,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD96_120,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD96_120,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD96_120,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),

                new TempForeRealCompare(ForeSpanType.FD120_144,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD120_144,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD120_144,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD120_144,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),

                new TempForeRealCompare(ForeSpanType.FD144_168,ForeFactorType.maxt,ForeClockType.H08,RealTempValueType.D18),
                new TempForeRealCompare(ForeSpanType.FD144_168,ForeFactorType.mint,ForeClockType.H08,RealTempValueType.D8),
                new TempForeRealCompare(ForeSpanType.FD144_168,ForeFactorType.maxt,ForeClockType.H20,RealTempValueType.D12),
                new TempForeRealCompare(ForeSpanType.FD144_168,ForeFactorType.mint,ForeClockType.H20,RealTempValueType.D2),
            };
#endregion

        }

        /// <summary>
        /// 给定日期，以及雨水条件，将需要算semi的entity条件都取出来
        /// </summary>
        /// <param name="type">雨水类型</param>
        /// <param name="dt">日期</param>
        /// <returns>条件数组</returns>
        public BaseForeRealCompare[] GetRainRelatedForeRecordConditions(RealRainValueType type, DateTime dt)
        {
            List<RainForeRealCompare> result = new List<RainForeRealCompare>();
            foreach (RainForeRealCompare compare in rainRealCompareList)
            {
                if (compare.RainType == type)
                {
                    compare.SetRealDate(dt);
                    result.Add(compare);
                }
            }
            return result.ToArray();   
        }

        /// <summary>
        /// 给定预报的情况，获取实况值对应的条件
        /// </summary>
        /// <param name="dt">预报日期</param>
        /// <param name="span">预报时间段</param>
        /// <param name="clock">起报时刻</param>
        /// <returns>预报实况对应关系</returns>
        public RainForeRealCompare GetForeRelatedRainCondition(DateTime dt, ForeSpanType span, ForeClockType clock)
        {
            RainForeRealCompare result = null;
            foreach (RainForeRealCompare compare in rainRealCompareList)
            {
                if (compare.Span == span && compare.Clock == clock)
                {
                    compare.SetForeDate(dt);
                    result = compare;
                    return result;
                }
            }
            return result;
        }

        /// <summary>
        /// 给定日期，以及气温条件，将需要算semi的entity条件都取出来
        /// </summary>
        /// <param name="type">气温类型</param>
        /// <param name="dt">日期</param>
        /// <returns>条件数组</returns>
        public BaseForeRealCompare[] GetTempRelatedForeRecordConditions(RealTempValueType type, DateTime dt)
        {
            List<TempForeRealCompare> result = new List<TempForeRealCompare>();
            foreach (TempForeRealCompare compare in tempRealCompareList)
            {
                if (compare.TempType == type)
                {
                    compare.SetRealDate(dt);
                    result.Add(compare);
                }
            }
            return result.ToArray();
        }

        /// <summary>
        /// 给定预报的情况，获取实况值对应的条件
        /// </summary>
        /// <param name="dt">预报日期</param>
        /// <param name="span">预报时间段</param>
        /// <param name="clock">起报时刻</param>
        /// <returns>预报实况对应关系</returns>
        public TempForeRealCompare GetForeRelatedTempCondition(DateTime dt, ForeSpanType span, ForeClockType clock, ForeFactorType factor )
        {
            TempForeRealCompare result = null;
            foreach (TempForeRealCompare compare in tempRealCompareList)
            {
                if (compare.Span == span && compare.Clock == clock && compare.Type == factor)
                {
                    compare.SetForeDate(dt);
                    result = compare;
                    return result;
                }
            }
            return result;
        }
    }



    public class BaseForeRealCompare
    {
        public ForeClockType Clock;
        public ForeFactorType Type;
        public ForeSpanType Span;
        /// <summary>
        /// 预报距今天的日数
        /// 如果今天是20号。 1表示19号。2表示18号
        /// </summary>
        public int PastDay;
        /// <summary>
        /// 是否是24小时间隔
        /// true表示是 00_24 之类的间隔
        /// false表示是 00_12,12_24 的间隔
        /// </summary>
        public bool Is24Hours;
        /// <summary>
        /// 是否是前12小时
        /// 如果是24小时，该值则为false
        /// true表示 00_12 false表示 12_24
        /// </summary>
        public bool IsFirst12;

        public DateTime RealDate;

        public DateTime ForeDate;

        public BaseForeRealCompare(ForeSpanType span,ForeClockType clock)
        {
            Span = span;
            Clock = clock;
            //针对span初始化 PastDay, Is24Hours, IsFirst12
            string strSpan = span.ToString().Replace("FD", "");
            string[] hours = strSpan.Split('_');
            int start = Convert.ToInt32(hours[0]);
            int end = Convert.ToInt32(hours[1]);


            if ((end - start) == 12)
            {
                Is24Hours = false;
                if ((end % 24) == 0)
                {//是后12小时的
                    IsFirst12 = false;
                    PastDay = end / 24;
                }
                else
                {
                    IsFirst12 = true;
                    PastDay = start / 24 + 1;
                }
            }
            else
            {
                Is24Hours = true;
                IsFirst12 = false;
                PastDay = end / 24;
            }
        }

        /// <summary>
        /// 给定实况的日期，获取ForeEntity对象
        /// </summary>
        /// <param name="date">实况日期</param>
        public void SetRealDate(DateTime date)
        {
            RealDate = date;
            ForeDate = date.AddDays(0 - PastDay);
        }

        /// <summary>
        /// 给定预报的日期，获取RealEntity对象
        /// </summary>
        /// <param name="date">预报日期</param>
        public void SetForeDate(DateTime date)
        {
            ForeDate = date;
            RealDate = date.AddDays(PastDay);
        }
    }

    /// <summary>
    /// 降水的预报与实况对照类
    /// 通过对这个类的筛选，可以得出相关的对应关系。便于使用
    /// </summary>
    public  class RainForeRealCompare : BaseForeRealCompare
    {        
        public RealRainValueType RainType;

        public RainForeRealCompare(ForeSpanType span, ForeClockType clock, RealRainValueType rainType):base(span,clock)
        {
            Type = ForeFactorType.wth;
            RainType = rainType;
        }
    }

    /// <summary>
    /// 温度的预报与实况对照类
    /// 通过对这个类的筛选，可以得出相关的对应关系。便于使用
    /// </summary>
    public class TempForeRealCompare : BaseForeRealCompare
    {
        public RealTempValueType TempType;
        public TempForeRealCompare(ForeSpanType span, ForeFactorType type, ForeClockType clock, RealTempValueType tempType)
            : base(span,clock)
        {
            Type = type;
            TempType = tempType;
        }
    }
}
